﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using RainEngine.SceneNodes;


namespace RainEngine.Controllers
{
    /// <summary>
    /// 控制一个相机对象。
    /// 使用鼠标控制相机上下左右旋转，键盘控制前进后退左右平移。
    /// 相机不能翻滚，只在水平面xz上移动。
    /// </summary>
    public class SampleCameraController : Controller
    {
        #region 构造函数和成员变量
        
        /// <summary>
        /// 要控制的相机。
        /// </summary>
        private CameraSceneNode camera;

        private MouseState originalMouseState;
        MouseState currentMouseState;
        MouseState previousMouseState;
        
        /// <summary>
        /// 相机允许俯仰的最大角度。
        /// </summary>
        private float elevation = 30;

        /// <summary>
        /// 创建一个FpsCameraController对象。
        /// </summary>
        /// <param name="engine">引擎</param>
        public SampleCameraController(RainGE engine): base(engine)
        {
            
        }
        #endregion

        /// <summary>
        /// 获取或设置相机允许俯仰的最大角度。
        /// </summary>
        public float Elevation
        {
            get { return elevation; }
            set { elevation = value; }
        }
        
        /// <summary>
        /// 主控制逻辑
        /// </summary>
        /// <param name="gameTime"></param>
        public override void ControllerAction(GameTime gameTime)
        {
            if (camera == null)
            {
                camera = (CameraSceneNode)controlledNode;
                this.originalMouseState = new MouseState(engine.GraphicsDevice .Viewport .Width / 2, engine.GraphicsDevice .Viewport .Height / 2, 0, ButtonState.Released, ButtonState.Released, ButtonState.Released, ButtonState.Released, ButtonState.Released);
                currentMouseState = Mouse.GetState();
                previousMouseState = Mouse.GetState();
            }
            float timeDifference = (float)gameTime.ElapsedGameTime.TotalMilliseconds / 1000.0f;
            ProcessInput(timeDifference);
        }

        private void ProcessInput(float ellapsedTime)
        {
            //相机的上下旋转
            float cameraPitch = 0;
            //相机的左右旋转
            float cameraYaw = 0;
            //前进后退
            float movement = 0;
            
            //相机每帧旋转和移动距离
            float rotationPerSecond = ellapsedTime * camera.RotationSpeed;
            float movementPerSecond = ellapsedTime * camera.MovementSpeed;

            currentMouseState = Mouse.GetState();           

            if (currentMouseState !=previousMouseState&&Input.MouseMiddleButtonPressed)
            {
                float xDifference = currentMouseState.X - previousMouseState.X;
                float yDifference = currentMouseState.Y - previousMouseState.Y;
                cameraYaw = xDifference;
                cameraPitch = -yDifference;

                //Quaternion fpsRotation = Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(-camera.AngleRotation.Y), 0, 0);
                //Vector3 addVector = Vector3.Transform(Vector3.Forward, fpsRotation);
                //camera.Pose.Position += addVector * movement;    
            }

            previousMouseState = currentMouseState;

            if (Input.MouseWheelDelta != 0)
            {
                movement += movementPerSecond;
            }          

            if (cameraYaw != 0 || cameraPitch != 0 || movement != 0)
            {
                //-------------------------
                //  当相机旋转时                        
                //-------------------------
                if (cameraYaw != 0 || cameraPitch != 0)
                {
                    Vector3 angleRotation = new Vector3(cameraPitch, cameraYaw, 0);
                    camera.AngleRotation += angleRotation;
                    camera.Pose.Rotation = Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(-camera.AngleRotation.Y), MathHelper.ToRadians(camera.AngleRotation.X), 0);
                    Vector3 aa = new Vector3(300 * (float)Math.Sin(MathHelper.ToRadians(cameraYaw)), 300-300 * (float)Math.Cos(MathHelper.ToRadians(cameraYaw)), 0);
                    
                    camera.Pose.Position += aa;
                        isDirty = true;
                    
                }

                //--------------------
                //  当相机前后移动时
                //--------------------
                if (movement != 0)
                {
                    isDirty = true;

                    Quaternion fpsRotation = Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(-camera.AngleRotation.Y), 0, 0);
                    Vector3 addVector = Vector3.Transform(Vector3.Forward, fpsRotation);
                    camera.Pose.Position += addVector *movement;                    
                }                

                //更新相机
                if (isDirty)
                {                    
                    camera.UpdateViewMatrix(true);
                    isDirty = false;
                }
            } 
        }
    }
}
